﻿using System;
using System.ComponentModel;
using System.Device.Location;
using System.Windows.Data;
using System.Windows.Threading;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Threading;
using Microsoft.WindowsAzure.MobileServices;
using SkiTracker.Model;
using System.Linq;
using Windows.Devices.Geolocation;

namespace SkiTracker.ViewModel
{
    public class ConversationViewModel : ViewModelBase
    {
        private readonly IMobileServiceTable<Message> _messageTable = App.MobileService.GetTable<Message>();
        private readonly DispatcherTimer _timer = new DispatcherTimer();

        public ConversationViewModel()
        {
            GetMessages();

            App.CurrentApp.NewMessageReceived += (sender, args) =>
                {
                    GetLatestMessages();
                    UpdateMessagesTime(); 
                };

            NavigateToMessageCommand = new RelayCommand<int>(id => App.RootFrame.Navigate(new Uri(string.Format(@"/View/ReadMessagePage.xaml?id={0}", id), UriKind.Relative)));

            SendCommand = new RelayCommand(Send, () => !string.IsNullOrEmpty(Message));
            SendFixCommand = new RelayCommand<string>(Send);

            RefreshCommand = new RelayCommand(Refresh);

            _timer.Interval = TimeSpan.FromMinutes(1);
            _timer.Tick += (sender, args) => UpdateMessagesTime();
            _timer.Start();

        }
        private async void GetLatestMessages()
        {
            var lastMessage = Messages.OrderByDescending(m => m.CreatedAt).FirstOrDefault();

            if (lastMessage == null)
            {
                DispatcherHelper.CheckBeginInvokeOnUI(GetMessages);
                return;
            }

            var newMessages = await _messageTable
                                        .Where(m => m.GroupName == App.CurrentApp.CurrentDevice.GroupName 
                                               && m.CreatedAt > lastMessage.CreatedAt)
                                        .OrderBy(m => m.CreatedAt)
                                        .ToListAsync();
            
            foreach (var newMessage in newMessages)
            {
                var message = newMessage;
                DispatcherHelper.CheckBeginInvokeOnUI(() => Messages.Add(message));
            }

            DispatcherHelper.CheckBeginInvokeOnUI(() => SortedMessages.View.MoveCurrentToLast());

        }

        private void GetMessages()
        {
            if (App.CurrentApp.CurrentDevice != null)
            {
                GetMessages(App.CurrentApp.CurrentDevice.GroupName);
            }
            else
            {
                App.CurrentApp.DeviceLoaded += (sender, args) 
                    => GetMessages(App.CurrentApp.CurrentDevice.GroupName);
            }
        }

        private void GetMessages(string groupName)
        {
            Messages = _messageTable
                .Where(m => m.GroupName == groupName)
                .OrderByDescending(m => m.CreatedAt)
                .Take(10)
                .ToCollectionView();

                SortedMessages = new CollectionViewSource {Source = Messages};
                SortedMessages.SortDescriptions.Add(new SortDescription("CreatedAt", ListSortDirection.Ascending));
                SortedMessages.View.MoveCurrentToLast();

                Messages.CollectionChanged += (sender, args) => SortedMessages.View.MoveCurrentToLast();
        }

        private MobileServiceCollectionView<Message> _messages;
        public MobileServiceCollectionView<Message> Messages
        {
            get { return _messages; }
            set 
            { 
                _messages = value;
                DispatcherHelper.CheckBeginInvokeOnUI(() => RaisePropertyChanged(() => Messages));
            }
        }

        private CollectionViewSource _sortedMessages;
        public CollectionViewSource SortedMessages
        {
            get { return _sortedMessages; }
            private set
            {
                _sortedMessages = value;
                DispatcherHelper.CheckBeginInvokeOnUI(() => RaisePropertyChanged(() => SortedMessages));
            }
        }

        public RelayCommand<int> NavigateToMessageCommand { get; private set; }

        private void Send()
        {
            Send(Message);
        }

        private async void Send(string messageText)
        {
            Message = string.Empty;

            var geolocator = new Geolocator
            {
                DesiredAccuracyInMeters = 30,
            };

            var currentLocation = await geolocator.GetGeopositionAsync(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15));

            var message = new Message
            {
                Text = messageText,
                DeviceId = App.CurrentApp.CurrentDevice.Id,
                GroupName = App.CurrentApp.CurrentDevice.GroupName,
                Coordinate = new GeoCoordinate(currentLocation.Coordinate.Latitude, currentLocation.Coordinate.Longitude),
            };

            await _messageTable.InsertAsync(message);

            //Messages.Add(message);
            GetLatestMessages();
        }

        private string _message;
        public string Message
        {
            get { return _message; }
            set
            {
                _message = value;
                RaisePropertyChanged(() => Message);
                SendCommand.RaiseCanExecuteChanged();
            }
        }

        public RelayCommand SendCommand { get; private set; }
        public RelayCommand<string> SendFixCommand { get; private set; }
        public RelayCommand RefreshCommand { get; private set; }

        private void Refresh()
        {
            GetLatestMessages();
            UpdateMessagesTime();
        }

        private void UpdateMessagesTime()
        {
            foreach (var message in Messages)
            {
                DispatcherHelper.CheckBeginInvokeOnUI(message.RaiseCreatedAtChanged);
            }
        }

    }
}
